/******************************************************************************

    Copyright (C) 2006 Alessio Stalla (alessiostalla@gmail.com)

    This file is part of PrettyProlog.

    PrettyProlog is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    PrettyProlog is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PrettyProlog; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    See the file COPYING for further details.

 *****************************************************************************/

package prettyprolog.engine;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import prettyprolog.datatypes.Constraint;
import prettyprolog.datatypes.Substitution;
import prettyprolog.datatypes.Term;
import prettyprolog.datatypes.Variable;

/**
 * Frames are objects that are pushed and popped on the Stack by the Engine.
 * Frames contain, among other things, the current Goal and Substitution, and
 * the index starting from which, when backtracking, the engine will search for
 * a Clause whose head unifies with the first subterm of the current Goal. Also,
 * frames contain a &quot;cut mark&quot; that is used by the implementation of
 * the cut.
 **/
public class Frame implements Serializable {
	
	private static final long serialVersionUID = 1L;

	/** The current Goal at the time this Frame is pushed on the Stack. */
	private Goal goal;
	
    private Constraint constraint;

    private Vector<Variable> ArcDomain;
    
    private Vector<Variable> BoundDomain;
	/**
	 * A printed representation of the Clause used to obtain the current Goal.
	 */
	private String clause;
	/**
	 * The current Substitution at the time the Frame is pushed on the Stack.
	 */
	private Substitution subst;
	/**
	 * The index starting from which, when backtracking, the engine will search
	 * for a Clause whose head unifies with the first subterm of the current
	 * Goal.
	 */
	private int index;
	/**
	 * A marker used by the Cut system predicate to decide which frames to
	 * remove from the stack.
	 */
	private int cut;
	
	private Frame next;
	
	private Map<Term, Term> data = new HashMap<Term, Term>();

	/**
	 * Creates a new Frame with the specified info.
	 * 
	 * @see #Frame(Goal, Substitution, int, String, int)
	 */
	public Frame(Goal g, Substitution s, int i, String cl, Constraint constr, Vector<Variable> ArcDom, Vector<Variable> BoundDom) {
		this(g, s, i, cl, 0, constr, ArcDom, BoundDom);
	}

	/**
	 * Creates a new Frame with the specified info.
	 * 
	 * @param g
	 *            the current Goal
	 * @param s
	 *            the current Substitution.
	 * @param i
	 *            the index from which to search the next Clause.
	 * @param cl
	 *            a printed representation of the Clause used to obtain g from
	 *            the previous Goal.
	 * @param c
	 *            the cut mark.
	 */
	public Frame(Goal g, Substitution s, int i, String cl, int c, Constraint cons, Vector<Variable> Arcdom, Vector<Variable> Bounddom) {
		goal = g;
		subst = s;
		index = i;
		clause = cl;
		cut = c;
        constraint = cons;
        ArcDomain = Arcdom;
        BoundDomain = Bounddom;
	}

	/** @return the current Goal. */
	public Goal getGoal() {
		return goal;
	}

	/** @return the current Substitution. */
	public Substitution getSubstitution() {
		return subst;
	}

	/** @return the index from which to search for the next Clause. */
	public int getIndex() {
		return index;
	}

	/** Sets the index from which to search for the next Clause. */
	protected void setIndex(int i) {
		index = i;
	}

	/**
	 * @return the printed representation of the Clause used to obtain the
	 *         current Goal.
	 */
	public String getClause() {
		return clause;
	}
	
    public Constraint getConstraint() {
        return constraint;
    }
    
    public void setArcDomain (Vector<Variable> Adom) {
    	this.ArcDomain = Adom;
    }
    
    public void setBoundDomain (Vector<Variable> Bdom) {
    	this.BoundDomain = Bdom;
    }

    public Vector<Variable> getArcDomain() {
        return ArcDomain;
    }
    
    public Vector<Variable> getBoundDomain() {
        return BoundDomain;
    }

	/** @return the cut mark. */
	public int getCutMark() {
		return cut;
	}

	/** Sets the cut mark. */
	protected void setCutMark(int i) {
		cut = i;
	}
	
	public Term getFrameData(Term t) {
		Term v = data.get(t);
		if(v == null && next != null) {
			v = next.getFrameData(t);
			if(v != null) {
				data.put(t, v);
			}
		}
		return v;
	}
	
	public Term putFrameData(Term k, Term v) {
		return data.put(k, v);
	}
	
	public void setNext(Frame next) {
		this.next = next;
	}
	
	public Frame getNext() {
		return next;
	}
	
}